package com.ysy.logistics.controller.stock;

import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ysy.common.resp.ResultData;
import com.ysy.logistics.entities.sale.CusOrder;
import com.ysy.logistics.entities.sale.CusOrderGoods;
import com.ysy.logistics.entities.stock.GoodsCapacity;
import com.ysy.logistics.entities.stock.InBoundList;
import com.ysy.logistics.entities.stock.StoreGoods;
import com.ysy.logistics.entities.stock.StoreHouse;
import com.ysy.logistics.entities.stock.dto.InBoundListDto;
import com.ysy.logistics.entities.stock.dto.PutSupGoodsDto;
import com.ysy.logistics.entities.supplier.SupGoods;
import com.ysy.logistics.entities.supplier.SupOrder;
import com.ysy.logistics.entities.supplier.SupOrderGoods;
import com.ysy.logistics.myannotation.OperateLog;
import com.ysy.logistics.service.sale.CusOrderGoodsService;
import com.ysy.logistics.service.sale.CusOrderService;
import com.ysy.logistics.service.stock.GoodsCapacityService;
import com.ysy.logistics.service.stock.InBoundListService;
import com.ysy.logistics.service.stock.StoreGoodsService;
import com.ysy.logistics.service.stock.StoreHouseService;
import com.ysy.logistics.service.supplier.SupGoodsService;
import com.ysy.logistics.service.supplier.SupOrderGoodsService;
import com.ysy.logistics.service.supplier.SupOrderService;
import com.ysy.logistics.util.PageInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @ClassDescription:
 * @Author:姚斯羽
 * @Create:2025/4/1 22:05
 **/
@Slf4j
@RestController
@RequestMapping(value = "/inBoundList", name = "入库单")
@Tag(name = "入库单", description = "出入库操作")
@CrossOrigin
public class InBoundListController {

    @Resource
    private SupOrderService supOrderService;
    @Resource
    SupOrderGoodsService supOrderGoodsService;
    @Resource
    SupGoodsService supGoodsService;
    @Resource
    private GoodsCapacityService goodsCapacityService;
    @Resource
    private StoreGoodsService storeGoodsService;

    @Resource
    private InBoundListService inBoundListService;

    @Resource
    private CusOrderService cusOrderService;
    @Resource
    private CusOrderGoodsService cusOrderGoodsService;
    @Resource
    private StoreHouseService storeHouseService;


    @PostMapping(value = "/listByPage")
    @Operation(summary = "分页查询入库单", description = "分页查询入库单")
    @OperateLog(value = "分页查询入库单")
    public ResultData<Page<InBoundList>> listByPage(@RequestBody PageInfo<InBoundList> pageInfo) {
        InBoundList criteria = pageInfo.getCriteria();
        if (Objects.isNull(criteria)) {
            return ResultData.fail("请输入必要参数");
        }
        //采购单入库
        if (StringUtils.equals("0", criteria.getInBoundType())) {
            PageInfo<SupOrder> orderPageInfo = new PageInfo<>();
            orderPageInfo.setSize(pageInfo.getSize());
            orderPageInfo.setCurrent(pageInfo.getCurrent());
            //条件
            SupOrder supOrder = new SupOrder();
            supOrder.setSupplierName(criteria.getInBoundResponsible());
            supOrder.setOrderNum(criteria.getOrderNum());
            //已收货 且未入库
            supOrder.setOrderStatus("2");
            supOrder.setStorageStatus(0);
            orderPageInfo.setCriteria(supOrder);
            Page<SupOrder> supOrderPage = supOrderService.listByPage(orderPageInfo);
            //构建返回分页
            Page<InBoundList> inBoundListDtoPage = new Page<>();
            inBoundListDtoPage.setCurrent(supOrderPage.getCurrent());
            inBoundListDtoPage.setSize(supOrderPage.getSize());
            inBoundListDtoPage.setTotal(supOrderPage.getTotal());
            List<SupOrder> records = supOrderPage.getRecords();
            if (!CollectionUtils.isEmpty(records)) {
                List<InBoundList> collect = records.stream().map(supOrderDto -> {
                    InBoundList InBoundList = new InBoundListDto();
                    InBoundList.setInBoundResponsible(supOrderDto.getSupplierName());
                    InBoundList.setOrderNum(supOrderDto.getOrderNum());
                    InBoundList.setInBoundType("0");
                    InBoundList.setInBoundTypeId(supOrderDto.getId());
                    return InBoundList;
                }).collect(Collectors.toList());
                inBoundListDtoPage.setRecords(collect);
            }
            return ResultData.success(inBoundListDtoPage);
        }else {
            PageInfo<CusOrder> orderPageInfo = new PageInfo<>();
            orderPageInfo.setSize(pageInfo.getSize());
            orderPageInfo.setCurrent(pageInfo.getCurrent());
            //条件
            CusOrder cusOrder = new CusOrder();
            cusOrder.setCustomerName(criteria.getInBoundResponsible());
            cusOrder.setOrderNum(criteria.getOrderNum());
            //已出库
            cusOrder.setOrderStatus(5);
            cusOrder.setStorageStatus(1);
            orderPageInfo.setCriteria(cusOrder);
            Page<CusOrder> supOrderPage = cusOrderService.listByPage(orderPageInfo);
            //构建返回分页
            Page<InBoundList> inBoundListDtoPage = new Page<>();
            inBoundListDtoPage.setCurrent(supOrderPage.getCurrent());
            inBoundListDtoPage.setSize(supOrderPage.getSize());
            inBoundListDtoPage.setTotal(supOrderPage.getTotal());
            List<CusOrder> records = supOrderPage.getRecords();
            if (!CollectionUtils.isEmpty(records)) {
                List<InBoundList> collect = records.stream().map(cus -> {
                    InBoundList InBoundList = new InBoundListDto();
                    InBoundList.setInBoundResponsible(cus.getCustomerName());
                    InBoundList.setOrderNum(cus.getOrderNum());
                    InBoundList.setInBoundType("1");
                    InBoundList.setInBoundTypeId(cus.getId());
                    return InBoundList;
                }).collect(Collectors.toList());
                inBoundListDtoPage.setRecords(collect);
            }
            return ResultData.success(inBoundListDtoPage);
        }
    }

    @GetMapping(value = "/getGoodsDetail/{id}/{type}")
    @Operation(summary = "获取入库单商品详情", description = "获取入库单商品详情")
    @OperateLog(value = "获取入库单商品详情")
    public ResultData getGoodsDetail(@PathVariable("id") String id, @PathVariable("type") String type) {
        //采购单入库
        if (StringUtils.equals("0", type)) {
            //根据采购单id查询商品详情
            List<SupGoods> supOrderGoods = supOrderGoodsService.listByOrderId(id);
            if (!CollectionUtils.isEmpty(supOrderGoods)) {
                List<PutSupGoodsDto> collect = supOrderGoods.stream().map(supGoods -> {
                    PutSupGoodsDto putSupGoodsDto = PutSupGoodsDto.convert(supGoods);
                    putSupGoodsDto.setExistGoodsCapacity(goodsCapacityService.existsEntity(GoodsCapacity.supGoodsToCapacity(supGoods)));
                    putSupGoodsDto.setTotal(supOrderGoodsService.totalGoods(id, supGoods.getId()));
                    return putSupGoodsDto;
                }).collect(Collectors.toList());
                return ResultData.success(collect);
            }
        } else {
            //根据订单Id查询商品
            LambdaQueryWrapper<CusOrderGoods> lqw = new LambdaQueryWrapper<>();
            lqw.eq(CusOrderGoods::getOrderId, id);
            List<CusOrderGoods> cusOrderGoods = cusOrderGoodsService.list(lqw);
            //查寻出商品
            if (!CollectionUtils.isEmpty(cusOrderGoods)) {
                List<String> goodsId = cusOrderGoods.stream().map(CusOrderGoods::getGoodsId).distinct().collect(Collectors.toList());
                LambdaQueryWrapper<SupGoods> supGoodsLQW = new LambdaQueryWrapper<>();
                supGoodsLQW.in(SupGoods::getId, goodsId);
                List<SupGoods> supGoods = supGoodsService.list(supGoodsLQW);
                if (!CollectionUtils.isEmpty(supGoods)) {
                    List<PutSupGoodsDto> collect = supGoods.stream().map(goods -> {
                        PutSupGoodsDto putSupGoodsDto = PutSupGoodsDto.convert(goods);
                        putSupGoodsDto.setExistGoodsCapacity(goodsCapacityService.existsEntity(GoodsCapacity.supGoodsToCapacity(goods)));
                        putSupGoodsDto.setTotal(cusOrderGoodsService.totalGoods(id, goods.getId()));
                        return putSupGoodsDto;
                    }).collect(Collectors.toList());
                    return ResultData.success(collect);
                }
            }
        }
        return ResultData.fail("未找到商品");
    }


    @GetMapping(value = "/calculateCapacity/{id}/{type}")
    @Operation(summary = "计算入库单总容量和商品是否存在规格", description = "计算入库单总容量和商品是否存在规格")
    public ResultData calculateCapacity(@PathVariable("id") String id, @PathVariable("type") String type) {
        //采购单入库
        Map<String, Object> result = new HashMap<>();
        Integer totalCapacity = 0;
        boolean flag = true;
        if (StringUtils.equals("0", type)) {
            //根据采购单id查询商品详情
            LambdaQueryWrapper<SupOrderGoods> lqw = new LambdaQueryWrapper<>();
            lqw.eq(SupOrderGoods::getOrderId, id);
            List<SupOrderGoods> supOrderGoods = supOrderGoodsService.list(lqw);
            if (CollectionUtils.isEmpty(supOrderGoods)) {
                return ResultData.fail("暂无商品");
            }
            for (int i = 0; i < supOrderGoods.size(); i++) {
                //先判断商品是否存在规格
                SupGoods byId = supGoodsService.getById(supOrderGoods.get(i).getGoodsId());
                GoodsCapacity byEntity = goodsCapacityService.getByEntity(GoodsCapacity.supGoodsToCapacity(byId));
                if (Objects.isNull(byEntity)) {
                    flag = false;
                    break;
                }
                //存在则计算容量
                totalCapacity += supOrderGoods.get(i).getGoodsNum() * byEntity.getCapacity();
            }

        } else {
            return ResultData.fail("提醒，暂未开发销售单入库");
        }
        result.put("totalCapacity", totalCapacity);
        result.put("flag", flag);
        return ResultData.success(result);
    }

    @PostMapping(value = "/save")
    @Operation(summary = "入库", description = "入库")
    @OperateLog(value = "入库")
    public ResultData save(@Validated @RequestBody InBoundList inBoundList) {
        log.debug("入库："+inBoundList);
        //根据入库类型查询商品
        if (StringUtils.equals("0", inBoundList.getInBoundType())){
           //查询订单商品
            LambdaQueryWrapper<SupOrderGoods> supOrderGoodsLambdaQueryWrapper = new LambdaQueryWrapper<>();
            supOrderGoodsLambdaQueryWrapper.eq(SupOrderGoods::getOrderId,inBoundList.getInBoundTypeId());
            List<SupOrderGoods> supOrderGoods = supOrderGoodsService.list(supOrderGoodsLambdaQueryWrapper);
            if (CollectionUtils.isEmpty(supOrderGoods)){
                return ResultData.fail("订单商品不存在");
            }
            //新增StoreGoods
            List<StoreGoods> addStoreGoodsList = new ArrayList<>();
            //更新StoreGoods
            List<StoreGoods> updateStoreGoodsList = new ArrayList<>();
            //增加的仓库容量
            Integer addStoreGoodsCapacity = 0;

            //查询出商品入库规格
            for (int i = 0; i < supOrderGoods.size(); i++) {
                SupOrderGoods orderGoods = supOrderGoods.get(i);
                //查询出商品
                SupGoods goods = supGoodsService.getById(orderGoods.getGoodsId());
                if (Objects.isNull(goods)){
                    return ResultData.fail("商品不存在");
                }
                //获取商品规格
                GoodsCapacity byEntity = goodsCapacityService.getByEntity(GoodsCapacity.supGoodsToCapacity(goods));
                if (Objects.isNull(byEntity)){
                   return ResultData.fail("商品规格不存在");
                }
                //存在查看对应仓库是否存在该商品
                LambdaQueryWrapper<StoreGoods> lqw = new LambdaQueryWrapper<>();
                lqw.eq(StoreGoods::getStoreHouseId,inBoundList.getWarehouseId())
                        .eq(StoreGoods::getGoodsCapacityId,byEntity.getId());
                StoreGoods one = storeGoodsService.getOne(lqw);
                if (Objects.isNull(one)){
                    //不存在新增
                    StoreGoods storeGoods = new StoreGoods();
                    storeGoods.setGoodsId(goods.getId());
                    storeGoods.setGoodsType(goods.getType());
                    storeGoods.setPrice(goods.getPrice());
                    storeGoods.setPriceUnit(goods.getPriceUnit());
                    storeGoods.setStoreHouseId(inBoundList.getWarehouseId());
                    storeGoods.setStoreHouseName(null);
                    storeGoods.setStoreNum(orderGoods.getGoodsNum());
                    storeGoods.setCreateTime(new Date());
                    storeGoods.setStatus("1");
                    storeGoods.setGoodsCapacityId(byEntity.getId());
                    addStoreGoodsList.add(storeGoods);

                }else {
                    //存在则修改库存
                    one.setStoreNum(one.getStoreNum()+orderGoods.getGoodsNum());
                    StoreGoods update = new StoreGoods();
                    update.setId(one.getId());
                    update.setStoreNum(one.getStoreNum());
                    updateStoreGoodsList.add(update);
                }
                addStoreGoodsCapacity += orderGoods.getGoodsNum()*byEntity.getCapacity();
            }
            //调用方法，开启事务
            return storeGoodsService.inbound(addStoreGoodsList,updateStoreGoodsList,inBoundList,addStoreGoodsCapacity);

        }else {
            return ResultData.fail("提醒，暂未开发销售单入库");
        }
    }

    @PostMapping(value = "/listPage")
    @Operation(summary = "库存明细", description = "库存明细")
    @OperateLog(value = "库存明细")
    public ResultData<Page<InBoundListDto>> listPage(@RequestBody PageInfo<InBoundListDto> pageInfo) {
        log.debug("分页查询库存明细："+pageInfo);
        //分页查询
        return ResultData.success(inBoundListService.listPage(pageInfo));
    }

    @GetMapping(value = "/backInBoundList/{id}")
    @Operation(summary = "回退入库单", description = "回退入库单")
    @OperateLog(value = "退货入库")
    public ResultData backInBoundList(@PathVariable("id") String id) {
        log.debug("回退入库单："+id);
        //查询出订单
        CusOrder byId = cusOrderService.getById(id);
        if (Objects.isNull(byId)){
            return ResultData.fail("订单不存在");
        }
        boolean flag =false;
        String resultStr = "";
        if (byId.getOrderStatus() == 4){
            flag = true;
            resultStr = "该订单已入库";
        } else if (byId.getOrderStatus() != 5){
            flag = true;
            resultStr = "该订单未退货，不能入库";
        }
        if (byId.getStorageStatus() == 0){
            flag = true;
            resultStr = "该订单未出库，不能入库";
        }
        if (flag){
            return ResultData.fail(resultStr);
        }
        //查询出商品
        List<CusOrderGoods> cusOrderGoods = cusOrderGoodsService.list(new LambdaQueryWrapper<CusOrderGoods>().eq(CusOrderGoods::getOrderId, id));
        if (CollectionUtils.isEmpty(cusOrderGoods)){
            return ResultData.fail("订单商品不存在");
        }
        //根据仓库Id分组
        Map<String, List<CusOrderGoods>> map = cusOrderGoods.stream().collect(Collectors.groupingBy(CusOrderGoods::getStoreHouseId));
        //构建入库单编号
        //供货商汉字首字母
        String OrderNo = PinyinUtil.getFirstLetter(byId.getCustomerName(), "").toUpperCase() +DateUtil.format(new Date(), "yyyyMMddHHmmss");

        //入库单
        List<InBoundList> newInBoundList = new ArrayList<>();
        //仓库信息
        List<StoreHouse> storeHouseList = new ArrayList<>();
        //商品信息
        List<StoreGoods> updateStoreGoodsList = new ArrayList<>();
        for (Map.Entry<String, List<CusOrderGoods>> entry : map.entrySet()) {
            String key = entry.getKey();
            List<CusOrderGoods> value = entry.getValue();
            InBoundList inBoundList = new InBoundList();
            inBoundList.setId(null)
                    .setInBoundNo(OrderNo)
                    .setInBoundType("1")
                    .setInBoundTypeId(id)
                    .setInBoundPerson("系统退货入库")
                    .setInBoundResponsible(byId.getCustomerName())
                    .setWarehouseId(key)
                    .setInBoundStatus("0")
                    .setOrderNum(byId.getOrderNum())
                    .setCreateTime(new Date());
            newInBoundList.add(inBoundList);
            //商品仓库信息
            Integer storeHouseNum = 0;
            for (int i = 0; i < value.size(); i++) {
                CusOrderGoods item = value.get(i);
                LambdaQueryWrapper<StoreGoods> lqw = new LambdaQueryWrapper<>();
                lqw.eq(StoreGoods::getStoreHouseId,key)
                        .eq(StoreGoods::getGoodsId,item.getGoodsId())
                        .eq(StoreGoods::getGoodsCapacityId,item.getGoodsCapacityId());
                StoreGoods one = storeGoodsService.getOne(lqw);
                if (!Objects.isNull(one)){
                    //查询出商品规格
                    GoodsCapacity byEntity = goodsCapacityService.getById(one.getGoodsCapacityId());
                    storeHouseNum +=item.getGoodsNum() * byEntity.getCapacity();
                    StoreGoods storeGoods = new StoreGoods();
                    storeGoods.setId(one.getId())
                            .setStoreNum(one.getStoreNum() + item.getGoodsNum());
                    updateStoreGoodsList.add(storeGoods);
                }
            }
            //判断仓库是否已满
            StoreHouse storeHouse = storeHouseService.getById(key);
            if (storeHouse.getCapacity() < storeHouseNum+storeHouse.getUsedCapacity()){
                return ResultData.fail("仓库容量不足,请稍后重试");
            }
            StoreHouse updateStoreHouse = new StoreHouse();
            updateStoreHouse.setId(storeHouse.getId());
            updateStoreHouse.setUsedCapacity(storeHouse.getUsedCapacity()+storeHouseNum);
            storeHouseList.add(updateStoreHouse);
        }
        //调用方法，开启事务
        return  storeGoodsService.saveBackInBound(newInBoundList,storeHouseList,updateStoreGoodsList);

    }
}
